
def listToBytes(list1):
	dataBytes = bytes()
	for i in list1:
		dataBytes += i.to_bytes(1, byteorder= 'little')
	return dataBytes

	
class pos:
	def __init__(self):
		self.x = 0
		self.y = 0
	def __str__(self):
		return "{x:"+str(self.x)+", y:"+str(self.y)+"}"
	def fromBytes(self, dataBytes):
		self.x = dataBytes[0]+(dataBytes[1]<<8)
		self.y = dataBytes[2]+(dataBytes[3]<<8)
	def toBytes(self):
		return self.x.to_bytes(2, byteorder='little')+self.y.to_bytes(2, byteorder='little')
class size:
	def __init__(self):
		self.width = 0
		self.height = 0
	def __str__(self):
		return "{width:"+str(self.width)+", height:"+str(self.height)+"}"
	def fromBytes(self, dataBytes):
		self.width = dataBytes[0]+(dataBytes[1]<<8)
		self.height = dataBytes[2]+(dataBytes[3]<<8)
	def toBytes(self):
		return self.width.to_bytes(2, byteorder='little')+self.height.to_bytes(2, byteorder='little')
class RS1_crop:
	def __init__(self):
		self.pos = pos()
		self.reset = 0
	def __str__(self):
		return "{x:" + str(self.pos.x)+\
			", y:" + str(self.pos.y)+\
			", reset:" + str(self.reset)+\
			"}"
	def fromBytes(self, dataBytes):
		self.pos.fromBytes(dataBytes)
		self.reset = dataBytes[4];
	def toBytes(self):
		return self.pos.toBytes()+\
			self.reset.to_bytes(1, byteorder='little')
class RS1_inputCrop:
	def __init__(self):
		self.forrs1 = 0
		self.rs1_crop = [RS1_crop()]*4
		for i in range(0, 4):
			self.rs1_crop[i] = RS1_crop()
	def __str__(self):
		return "{forsr1:" + str(self.forrs1)+\
			", crop1:" + str(self.rs1_crop[0])+\
			", crop2:" + str(self.rs1_crop[1])+\
			", crop3:" + str(self.rs1_crop[2])+\
			", crop4:" + str(self.rs1_crop[3])+\
			"}"
	def fromBytes(self, dataBytes):
		for i in range(0, 4):		
			self.rs1_crop[i].fromBytes(dataBytes[i*5:])
	def toBytes(self):
		return self.rs1_crop[0].toBytes()+self.rs1_crop[1].toBytes()+\
			self.rs1_crop[2].toBytes()+self.rs1_crop[3].toBytes()
class RS1_layer:
	def __init__(self):
		self.pos = pos()
		self.size = size()
		self.angle = 0
		self.input = 255
	def __str__(self):
		return "{size:"+str(self.size)+\
			", pos:"+str(self.pos)+\
			", angle:"+str(self.angle)+\
			", input:"+str(self.input)+\
			"}"
	def fromBytes(self, dataBytes):
		self.size.fromBytes(dataBytes)
		self.angle = dataBytes[4]+(dataBytes[5]<<8)
		self.pos = fromBytes(dataBytes[6:])
		self.input = dataBytes[10]
	def toBytes(self):
		return self.size.toBytes()+\
			self.angle.to_bytes(2, byteorder='little')+\
			self.pos.toBytes()+\
			self.input.to_bytes(1, byteorder='little')
			
class RS1_pmWppos:
	def __init__(self):
		self.pos = [pos()]*4
		for i in range(0, 4):
			self.pos[i] = pos()
			
		self.rotate = 0
	def __str__(self):
		return "{tl:"+str(self.pos[0])+\
			", tr:"+str(self.pos[1])+\
			", bl:"+str(self.pos[2])+\
			", br:"+str(self.pos[3])+\
			", rotate:"+str(self.rotate)+\
			"}"
	def fromBytes(self, dataBytes):
		for i in range(0, 4):
			self.pos[i].fromBytes(dataBytes[i*4:])
		self.rotate = dataBytes[16]
	def toBytes(self):
		return self.pos[0].toBytes()+\
			self.pos[1].toBytes()+\
			self.pos[2].toBytes()+\
			self.pos[3].toBytes()+\
			self.rotate.to_bytes(1, byteorder='little')
class RS1_egb:
	def __init__(self):
		self.size = size()
		self.gamma_en = 0
		self.gamma_r = 0
		self.gamma_g = 0
		self.gamma_b = 0
		self.en = 0
		self.len = 0
		self.ren = 0
		self.ten = 0
		self.ben = 0
	def __str__(self):
		return "{size:"+str(self.size)+\
			", "
class RS1_set:
	def __init__(self, MaxInput=13, MaxOutput=40):
		self.RS1_inputCrop = [RS1_inputCrop()]*MaxInput
		for i in range(0, MaxInput):
			self.RS1_inputCrop[i] = RS1_inputCrop()
		self.RS1_pmWppos = [RS1_pmWppos()]*MaxOutput
		self.RS1_layer = [RS1_layer()]*MaxOutput
		for i in range(0, MaxOutput):
			self.RS1_pmWppos[i] = RS1_pmWppos()
			self.RS1_layer[i] = RS1_layer()
	def __str__(self):
		result = "{"
		for i in range(0, len(self.RS1_inputCrop)):
			result += "input{:2d}:".format(i)+str(self.RS1_inputCrop[i])+", \n"
			
		for i in range(0, len(self.RS1_pmWppos)):
			result += "pmWppos{:2d}:".format(i)+str(self.RS1_pmWppos[i])+", \n"
			
		result += "}"
		return result
class container:
	def __init__(self):
		self.scaleVal = 0
		self.rect = rect()
		self.row = 2;
		self.col = 2;
		self.onOff = 0;
		self.color = 0;
		self.mode = 0;
		self.effectMode = 0;
		self.alphaTime = 1000;
		self.alpha = 0;
		self.black = 0;
	def __str__(self):
		return "{"+"onOff:{}".format(self.onOff)+\
			", rect:"+str(self.rect)+\
			", mode:{}".format(self.mode)+\
			", effectMode:{}".format(self.effectMode)+\
			"}"
	def fromBytes(self, dataBytes):
		self.rect = rect.fromBytes(dataBytes)
		self.scaleVal = dataBytes[8]+(dataBytes[9]<<8)
		self.mode = dataBytes[10]
		self.color = dataBytes[11]
		self.onOff = dataBytes[12]
		self.effectMode = dataBytes[13]
	def toBytes(self):
		return self.rect.toBytes()+\
			self.scaleVal.to_bytes(2, byteorder='little')+\
			self.mode.to_bytes(1, byteorder='little')+\
			self.color.to_bytes(1, byteorder='little')+\
			self.onOff.to_bytes(1, byteorder='little')+\
			self.effectMode.to_bytes(1, byteorder='little')
class H264_cap:
	def __init__(self):
		self.width = 1920
		self.height = 1080
		self.vfreq = 30
		self.bitrate = 2000
		self.enc_profile = 0
	def __str__(self):
		return "{"+"res:{}x{}@{}".format(self.width, self.height, self.vfreq)+\
			", bitrate:{}kbps".format(self.bitrate)+\
			", profile:{}".format(self.enc_profile)+\
			"}"
	def fromBytes(self, dataBytes):
		self.vfreq = dataBytes[0]
		self.width = dataBytes[1]+(dataBytes[2]<<8)
		self.height = dataBytes[3]+(dataBytes[4]<<8)
		self.bitrate = dataBytes[5]+(dataBytes[6]<<8)
		self.enc_profile = dataBytes[7]
	def toBytes(self):
		return self.vfreq.to_bytes(1, byteorder='little')+\
			self.width.to_bytes(2, byteorder='little')+\
			self.height.to_bytes(2, byteorder='little')+\
			self.bitrate.to_bytes(2, byteorder='little') +\
			self.enc_profile.to_bytes(1, byteorder='little')
class H264_network:
	def __init__(self):
		self.ip = [192,168,0,100]
		self.netmask = [255, 255, 255, 0]
		self.gateway = [192, 168, 0, 1]
		self.mac = [0x20, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e]
		self.dns = [8, 8, 8, 8]
	def __str__(self):
		return "{IP:"+"{}.{}.{}.{}".format(self.ip[0], self.ip[1], self.ip[2], self.ip[3])+\
			", DefGW:{}.{}.{}.{}".format(self.gateway[0], self.gateway[1], self.gateway[2], self.gateway[3])+\
			", NetMask:{}.{}.{}.{}".format(self.netmask[0], self.netmask[1], self.netmask[2], self.netmask[3])+\
			", MAC:{:02X}-{:02X}-{:02X}-{:02X}-{:02X}-{:02X}".format(self.mac[0],self.mac[1], \
			self.mac[2], self.mac[3], self.mac[4], self.mac[5])+"}"
	
	def fromBytes(self, dataBytes):
		for i in range(0, 4):
			self.ip[i] = dataBytes[i]
			self.netmask[i] = dataBytes[4+i]
			self.gateway[i] = dataBytes[8+i]
		for i in range(0, 6):
			self.mac[i] = dataBytes[12+i]
		
	def toBytes(self):
		return listToBytes(self.ip)+listToBytes(self.netmask)+listToBytes(self.gateway)+listToBytes(self.mac)
		
class H264_core:
	def __init__(self):
		self.network0 = H264_network()
		self.network1 = H264_network()
		self.cap = H264_cap()
	def __str__(self):
		return "{network0:" + str(self.network0) +\
			", network1:" + str(self.network1) +\
			", cap:" + str(self.cap) +\
			"}"
	def networkFromBytes(self, dataBytes):
		self.network0.fromBytes(dataBytes)
		self.network1.fromBytes(dataBytes[18:])
		for i in range(0, 4):
			self.network0.dns[i] = dataBytes[36+i]
			self.network1.dns[i] = dataBytes[40+i]
	def networkToBytes(self):
		return self.network0.toBytes()+self.network1.toBytes()+\
			listToBytes(self.network0.dns)+listToBytes(self.network1.dns)
	def capFromBytes(self, dataBytes):
		self.cap.fromBytes(dataBytes)
	def capToBytes(self):
		return self.cap.toBytes()

class H264_set:
	def __init__(self):
		self.core0 = H264_core()
		self.core1 = H264_core()
	def __str__(self):
		return "{core0:" +str(self.core0)+\
			", core1:" + str(self.core1) +\
			"}"
	def networkFromBytes(self, dataBytes):
		self.core0.networkFromBytes(dataBytes)
		self.core1.networkFromBytes(dataBytes[44:])
	def networkToBytes(self):
		return self.core0.networkToBytes()+self.core1.networkToBytes()
	def capFromBytes(self, dataBytes):
		self.core0.capFromBytes(dataBytes)
		self.core1.capFromBytes(dataBytes[8:])
	def capToBytes(self):
		return self.core0.capToBytes()+self.core1.capToBytes()
		
class rect:
	def __init__(self, x=0, y=0, w=1920, h=1080):
		self.x = x
		self.y = y
		self.w = w
		self.h = h
	def __str__(self):
		return "{x:"+str(self.x)+",y:"+str(self.y)+",w:"+str(self.w)+",h:"+str(self.h)+"}"
	def fromBytes(dataBytes):
		rect1 = rect()
		rect1.x = dataBytes[0]+(dataBytes[1]<<8)
		rect1.y = dataBytes[2]+(dataBytes[3]<<8)
		rect1.w = dataBytes[4]+(dataBytes[5]<<8)
		rect1.h = dataBytes[6]+(dataBytes[7]<<8)
		return rect1
	def toBytes(self):
		return self.x.to_bytes(2, byteorder= 'little')+\
			self.y.to_bytes(2, byteorder='little')+\
			self.w.to_bytes(2, byteorder='little')+\
			self.h.to_bytes(2, byteorder='little')

class layer:
	def __init__(self, scale=rect(), crop=rect(), input=0, freeze=0, flip=0, alpha=0, pos=0):
		self.scale = scale
		self.crop = crop
		self.input = input
		self.freeze = freeze
		self.flip = flip
		self.alpha = alpha
		self.pos = pos
	def __str__(self):
		return "{input:"+"{:2d}".format(self.input)+", scale:"+str(self.scale)+", crop:"+str(self.crop)+\
			", alpha:"+str(self.alpha)+", pos:"+str(self.pos)+"}"		
	def fromBytes(self, dataBytes):
		if(len(dataBytes)<18):
			print("layer.fromBytes() len error =", len(dataBytes))
			return
		crop = rect.fromBytes(dataBytes)
		scale = rect.fromBytes(dataBytes[8:])
		input = dataBytes[18]
		freeze = dataBytes[16]
		flip = dataBytes[17]
		self.crop = crop
		self.scale = scale
		self.input = input
		self.freeze = freeze
		self.flip = flip
		if(len(dataBytes)>=21):
			self.alpha = dataBytes[19]
			self.pos = dataBytes[20]
		
		return self
	def toBytes(self):
		return self.crop.toBytes()+self.scale.toBytes()+\
			self.freeze.to_bytes(1, byteorder='little')+\
			self.flip.to_bytes(1, byteorder='little')+\
			self.input.to_bytes(1, byteorder='little')
	def toLayerBytes(self):
		return self.toBytes()+\
			self.alpha.to_bytes(1, byteorder='little')+\
			self.pos.to_bytes(1, byteorder='little')
class other:
	def __init__(self):
		self.currentView = 0
class view:
	def __init__(self, maxLayer=16, maxInputBoard=13, maxOutput=40):
		self.layer = [layer()]*maxLayer
		for i in range(0, maxLayer):
			self.layer[i] = layer(pos=maxLayer-1-i)
		self.other = other()
		self.name = bytes(16)
		self.rs1_set = RS1_set(maxInputBoard, maxOutput)
	def __str__(self):
		result = "view{}:".format(self.other.currentView)+"{\n"
		for i in range(0, len(self.layer)):
			result+="layer{:2d}:".format(i)+str(self.layer[i])+"\n"
		result += "}"
		return result
	def fromBytes(self, dataBytes):
		if(len(dataBytes)<(21*len(self.layer)+16)):
			print("view.formBytes() len error =", len(dataBytes))
			return
		for i in range(0, len(self.layer)):
			self.layer[i].fromBytes(dataBytes[21*i:])
		self.name = dataBytes[21*len(self.layer):21*len(self.layer)+16]
	def toBytes(self):
		dataBytes = bytes()
		for i in range(0, len(self.layer)):
			dataBytes += self.layer[i].toLayerBytes()
		dataBytes += self.name
		return dataBytes
	def printValidLayer(self):
		result = "view{}:".format(self.other.currentView)+"{\n"
		for i in range(0, len(self.layer)):
			if(self.layer[i].alpha>0):
				result+="layer{:2d}:".format(i)+str(self.layer[i])+"\n"
		result += "}"
		print(result)
	

class inputSet:
	def __init__(self, scale=rect(), crop=rect(), input=0, freeze=0, flip=0, alpha=128):
		self.scale = scale
		self.crop = crop
		self.input = input
		self.freeze = freeze
		self.flip = flip
		self.alpha = alpha
		self.layerOnOff = 0x01
		self.brightness = 50
		self.contrast = 50
		self.sharpness = 50
		self.saturation = 50
		self.colorTempRed = 50
		self.colorTempGreen = 50
		self.colorTempBlue = 50
		self.rotate = 0
		self.gainR = 50
		self.gainG = 50
		self.gainB = 50
		self.hue = 50
		
	
	def __str__(self):
		return "{input:"+str(self.input)+", scale:"+str(self.scale)+", crop:"+str(self.crop)+\
			", alpha:"+str(self.alpha)+", layerOnOff:{:02X}".format(self.layerOnOff)+"}"
	
	def fromBytes(self, dataBytes):
		self.crop = rect.fromBytes(dataBytes)
		self.scale = rect.fromBytes(dataBytes[8:])
		self.input = dataBytes[18]
		self.freeze = dataBytes[16]
		self.flip = dataBytes[17]
		self.alpha = dataBytes[19]
		self.layerOnOff = dataBytes[20]
		if(len(dataBytes)>=28):
			self.brightness = dataBytes[21]
			self.contrast = dataBytes[22]
			self.sharpness = dataBytes[23]
			self.saturation = dataBytes[24]
			self.colorTempRed = dataBytes[25]
			self.colorTempGreen = dataBytes[26]
			self.colorTempBlue = dataBytes[27]
			
		if(len(dataBytes)>=33):
			self.rotate = dataBytes[28]
			self.gainR = dataBytes[29]
			self.gainG = dataBytes[30]
			self.gainB = dataBytes[31]
			self.hue = dataBytes[32]
		return self
	def toBytes(self):
		return self.crop.toBytes()+self.scale.toBytes()+\
			self.freeze.to_bytes(1, byteorder='little')+\
			self.flip.to_bytes(1, byteorder='little')+\
			self.input.to_bytes(1, byteorder='little')+\
			self.alpha.to_bytes(1, byteorder='little')+\
			self.layerOnOff.to_bytes(1, byteorder='little')+\
			self.brightness.to_bytes(1, byteorder='little')+\
			self.contrast.to_bytes(1, byteorder='little')+\
			self.sharpness.to_bytes(1, byteorder='little')+\
			self.saturation.to_bytes(1, byteorder='little')+\
			self.colorTempRed.to_bytes(1, byteorder='little')+\
			self.colorTempGreen.to_bytes(1, byteorder='little')+\
			self.colorTempBlue.to_bytes(1, byteorder='little')+\
			self.rotate.to_bytes(1, byteorder='little')+\
			self.gainR.to_bytes(1, byteorder='little')+\
			self.gainG.to_bytes(1, byteorder='little')+\
			self.gainB.to_bytes(1, byteorder='little')+\
			self.hue.to_bytes(1, byteorder='little')
			
class inputSource:
	def __init__(self, type=0, format=0x7f, width=1920, height=1080, vfreq=60):
		self.type = type
		self.format = format
		self.width = width
		self.height = height
		self.vfreq = vfreq
	def __str__(self):
		return "{type:"+str(self.type)+", format:"+str(self.format)+", width:"+str(self.width)+\
			", height:"+str(self.height)+", vfreq:{}".format(self.vfreq)+"}"
class network:
	def __init__(self):
		self.IP_adr = [192, 168, 0, 100]
		self.DefGW = [192, 168, 0, 1]
		self.NetMask = [255, 255, 255, 0]
		self.MAC_adr = [0, 0, 0, 0, 0, 0]
		self.DHCP = 0
	def __str__(self):
		return "{IP:"+"{}.{}.{}.{}".format(self.IP_adr[0], self.IP_adr[1], self.IP_adr[2], self.IP_adr[3])+\
			", DHCP:{}".format(self.DHCP)+\
			", DefGW:{}.{}.{}.{}".format(self.DefGW[0], self.DefGW[1], self.DefGW[2], self.DefGW[3])+\
			", NetMask:{}.{}.{}.{}".format(self.NetMask[0], self.NetMask[1], self.NetMask[2], self.NetMask[3])+\
			", MAC:{:02X}-{:02X}-{:02X}-{:02X}-{:02X}-{:02X}".format(self.MAC_adr[0],self.MAC_adr[1], \
			self.MAC_adr[2], self.MAC_adr[3], self.MAC_adr[4], self.MAC_adr[5])+"}"
if __name__ == "__main__":
	rect1 = rect.fromBytes(b'\x00\x00\x00\x00\x80\x078\x04\x00')
	print("rect:", rect1)
	print("rect:", rect1.toBytes(), len(rect1.toBytes()))
	print(rect.fromBytes(rect1.toBytes()))
	layer1 = layer()
	print(layer1)
	print(layer1.toBytes())
	print(layer1.fromBytes(layer1.toBytes()))
	
	layer2 = layer()
	layer2.fromBytes(b'\x00\x00\x00\x00\x80\x078\x04\x00\x008\x04\x80\x078\x04\x00\x000\x80O\xc1')
	print(layer2)
	inputSet1 = inputSet();
	print(inputSet1)
	print("inputSet1:", inputSet1.toBytes())
	inputSet2 = inputSet()
	inputSet2.fromBytes(inputSet1.toBytes())
	print("inputSet2:", inputSet2)
	view1 = view()
	print(view1)
	print(view1.rs1_set)
	#print(view1.toBytes())
	#view1.fromBytes(view1.toBytes())
	#print(view1)
	print(network())
	h264_set1 = H264_set()
	h264_set1.networkFromBytes(h264_set1.networkToBytes())
	h264_set1.capFromBytes(h264_set1.capToBytes())
	print(h264_set1)
	print(len(h264_set1.networkToBytes()))
